{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 144,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 168,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>grade</th>\n",
       "      <th>sub_grade</th>\n",
       "      <th>short_emp</th>\n",
       "      <th>emp_length_num</th>\n",
       "      <th>home_ownership</th>\n",
       "      <th>dti</th>\n",
       "      <th>purpose</th>\n",
       "      <th>term</th>\n",
       "      <th>last_delinq_none</th>\n",
       "      <th>last_major_derog_none</th>\n",
       "      <th>revol_util</th>\n",
       "      <th>total_rec_late_fee</th>\n",
       "      <th>safe_loans</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>19847</td>\n",
       "      <td>C</td>\n",
       "      <td>C3</td>\n",
       "      <td>0</td>\n",
       "      <td>11</td>\n",
       "      <td>MORTGAGE</td>\n",
       "      <td>20.18</td>\n",
       "      <td>debt_consolidation</td>\n",
       "      <td>36 months</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>80.2</td>\n",
       "      <td>0.0000</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>24186</td>\n",
       "      <td>D</td>\n",
       "      <td>D2</td>\n",
       "      <td>0</td>\n",
       "      <td>5</td>\n",
       "      <td>RENT</td>\n",
       "      <td>21.19</td>\n",
       "      <td>debt_consolidation</td>\n",
       "      <td>36 months</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>47.6</td>\n",
       "      <td>0.0000</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>40013</td>\n",
       "      <td>B</td>\n",
       "      <td>B5</td>\n",
       "      <td>0</td>\n",
       "      <td>11</td>\n",
       "      <td>MORTGAGE</td>\n",
       "      <td>30.90</td>\n",
       "      <td>debt_consolidation</td>\n",
       "      <td>36 months</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>90.1</td>\n",
       "      <td>0.0000</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>5405</td>\n",
       "      <td>B</td>\n",
       "      <td>B1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>MORTGAGE</td>\n",
       "      <td>22.17</td>\n",
       "      <td>debt_consolidation</td>\n",
       "      <td>36 months</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>40.1</td>\n",
       "      <td>0.0000</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>20203</td>\n",
       "      <td>F</td>\n",
       "      <td>F4</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>RENT</td>\n",
       "      <td>21.94</td>\n",
       "      <td>debt_consolidation</td>\n",
       "      <td>60 months</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>34.5</td>\n",
       "      <td>0.0000</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>12408</td>\n",
       "      <td>B</td>\n",
       "      <td>B5</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "      <td>RENT</td>\n",
       "      <td>8.56</td>\n",
       "      <td>debt_consolidation</td>\n",
       "      <td>36 months</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>34.4</td>\n",
       "      <td>0.0000</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>31935</td>\n",
       "      <td>B</td>\n",
       "      <td>B2</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>RENT</td>\n",
       "      <td>9.68</td>\n",
       "      <td>debt_consolidation</td>\n",
       "      <td>36 months</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>78.6</td>\n",
       "      <td>0.0000</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>4621</td>\n",
       "      <td>D</td>\n",
       "      <td>D1</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>MORTGAGE</td>\n",
       "      <td>3.78</td>\n",
       "      <td>other</td>\n",
       "      <td>36 months</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>70.4</td>\n",
       "      <td>14.9409</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>30060</td>\n",
       "      <td>C</td>\n",
       "      <td>C3</td>\n",
       "      <td>0</td>\n",
       "      <td>6</td>\n",
       "      <td>MORTGAGE</td>\n",
       "      <td>14.60</td>\n",
       "      <td>debt_consolidation</td>\n",
       "      <td>60 months</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>39.0</td>\n",
       "      <td>0.0000</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>8089</td>\n",
       "      <td>D</td>\n",
       "      <td>D3</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "      <td>OWN</td>\n",
       "      <td>17.85</td>\n",
       "      <td>debt_consolidation</td>\n",
       "      <td>36 months</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>70.7</td>\n",
       "      <td>0.3500</td>\n",
       "      <td>-1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      grade sub_grade  short_emp  emp_length_num home_ownership    dti  \\\n",
       "19847     C        C3          0              11       MORTGAGE  20.18   \n",
       "24186     D        D2          0               5           RENT  21.19   \n",
       "40013     B        B5          0              11       MORTGAGE  30.90   \n",
       "5405      B        B1          1               1       MORTGAGE  22.17   \n",
       "20203     F        F4          0               3           RENT  21.94   \n",
       "12408     B        B5          0               7           RENT   8.56   \n",
       "31935     B        B2          0               3           RENT   9.68   \n",
       "4621      D        D1          0               3       MORTGAGE   3.78   \n",
       "30060     C        C3          0               6       MORTGAGE  14.60   \n",
       "8089      D        D3          0               7            OWN  17.85   \n",
       "\n",
       "                  purpose        term  last_delinq_none  \\\n",
       "19847  debt_consolidation   36 months                 1   \n",
       "24186  debt_consolidation   36 months                 0   \n",
       "40013  debt_consolidation   36 months                 0   \n",
       "5405   debt_consolidation   36 months                 1   \n",
       "20203  debt_consolidation   60 months                 0   \n",
       "12408  debt_consolidation   36 months                 1   \n",
       "31935  debt_consolidation   36 months                 1   \n",
       "4621                other   36 months                 1   \n",
       "30060  debt_consolidation   60 months                 0   \n",
       "8089   debt_consolidation   36 months                 1   \n",
       "\n",
       "       last_major_derog_none  revol_util  total_rec_late_fee  safe_loans  \n",
       "19847                      1        80.2              0.0000           1  \n",
       "24186                      1        47.6              0.0000           1  \n",
       "40013                      1        90.1              0.0000          -1  \n",
       "5405                       1        40.1              0.0000          -1  \n",
       "20203                      1        34.5              0.0000           1  \n",
       "12408                      1        34.4              0.0000          -1  \n",
       "31935                      1        78.6              0.0000           1  \n",
       "4621                       1        70.4             14.9409          -1  \n",
       "30060                      1        39.0              0.0000           1  \n",
       "8089                       1        70.7              0.3500          -1  "
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "(40000, 13)"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "data = pd.read_csv('dataset/loans.csv').sample(40000)\n",
    "display(data.sample(10))\n",
    "display(data.shape)\n",
    "# grade: 贷款级别\n",
    "# sub_grade: 贷款细分级别\n",
    "# short_emp: 一年以内短期雇佣\n",
    "# emp_length_num:　受雇年限\n",
    "# home_ownership:居住状态（自有，按揭，租住）\n",
    "# dti：贷款占收入比例\n",
    "# purpose:贷款用途\n",
    "# term:贷款周期\n",
    "# last_delinq_none:贷款申请人是否有不良记录　\n",
    "# last_major_derog_none:贷款申请人是否有还款逾期90天以上记录\n",
    "# reｖol_util：透支额度占信用比例\n",
    "# total_rec_late_fee:逾期罚款总额\n",
    "# safe_loans:贷款是否安全\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 169,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.preprocessing import LabelEncoder\n",
    "from collections import defaultdict"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 170,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>grade</th>\n",
       "      <th>sub_grade</th>\n",
       "      <th>short_emp</th>\n",
       "      <th>emp_length_num</th>\n",
       "      <th>home_ownership</th>\n",
       "      <th>dti</th>\n",
       "      <th>purpose</th>\n",
       "      <th>term</th>\n",
       "      <th>last_delinq_none</th>\n",
       "      <th>last_major_derog_none</th>\n",
       "      <th>revol_util</th>\n",
       "      <th>total_rec_late_fee</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>4104</td>\n",
       "      <td>2</td>\n",
       "      <td>12</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1764</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>320</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18915</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>3</td>\n",
       "      <td>1608</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>240</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>44721</td>\n",
       "      <td>1</td>\n",
       "      <td>8</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "      <td>3</td>\n",
       "      <td>3240</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>561</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>21933</td>\n",
       "      <td>0</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "      <td>2328</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>325</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>20111</td>\n",
       "      <td>2</td>\n",
       "      <td>14</td>\n",
       "      <td>0</td>\n",
       "      <td>8</td>\n",
       "      <td>0</td>\n",
       "      <td>1048</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>280</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>13839</td>\n",
       "      <td>3</td>\n",
       "      <td>16</td>\n",
       "      <td>0</td>\n",
       "      <td>11</td>\n",
       "      <td>0</td>\n",
       "      <td>2025</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>817</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>15773</td>\n",
       "      <td>3</td>\n",
       "      <td>17</td>\n",
       "      <td>0</td>\n",
       "      <td>11</td>\n",
       "      <td>2</td>\n",
       "      <td>1483</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>958</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>27211</td>\n",
       "      <td>2</td>\n",
       "      <td>14</td>\n",
       "      <td>0</td>\n",
       "      <td>6</td>\n",
       "      <td>3</td>\n",
       "      <td>1701</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>157</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>17372</td>\n",
       "      <td>2</td>\n",
       "      <td>11</td>\n",
       "      <td>0</td>\n",
       "      <td>11</td>\n",
       "      <td>0</td>\n",
       "      <td>489</td>\n",
       "      <td>2</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>279</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>5410</td>\n",
       "      <td>2</td>\n",
       "      <td>14</td>\n",
       "      <td>0</td>\n",
       "      <td>11</td>\n",
       "      <td>0</td>\n",
       "      <td>1785</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>755</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>800 rows × 12 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "       grade  sub_grade  short_emp  emp_length_num  home_ownership   dti  \\\n",
       "4104       2         12          1               1               0  1764   \n",
       "18915      0          3          0               2               3  1608   \n",
       "44721      1          8          0               7               3  3240   \n",
       "21933      0          2          0               3               0  2328   \n",
       "20111      2         14          0               8               0  1048   \n",
       "...      ...        ...        ...             ...             ...   ...   \n",
       "13839      3         16          0              11               0  2025   \n",
       "15773      3         17          0              11               2  1483   \n",
       "27211      2         14          0               6               3  1701   \n",
       "17372      2         11          0              11               0   489   \n",
       "5410       2         14          0              11               0  1785   \n",
       "\n",
       "       purpose  term  last_delinq_none  last_major_derog_none  revol_util  \\\n",
       "4104         2     0                 0                      1         320   \n",
       "18915        1     0                 0                      1         240   \n",
       "44721        1     0                 1                      1         561   \n",
       "21933        1     0                 1                      1         325   \n",
       "20111        2     0                 0                      1         280   \n",
       "...        ...   ...               ...                    ...         ...   \n",
       "13839        2     1                 1                      1         817   \n",
       "15773        2     0                 0                      1         958   \n",
       "27211        2     1                 1                      1         157   \n",
       "17372        2     1                 0                      0         279   \n",
       "5410         1     1                 0                      0         755   \n",
       "\n",
       "       total_rec_late_fee  \n",
       "4104                    0  \n",
       "18915                   0  \n",
       "44721                   0  \n",
       "21933                   0  \n",
       "20111                   0  \n",
       "...                   ...  \n",
       "13839                   0  \n",
       "15773                   0  \n",
       "27211                   0  \n",
       "17372                   0  \n",
       "5410                    0  \n",
       "\n",
       "[800 rows x 12 columns]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>grade</th>\n",
       "      <th>sub_grade</th>\n",
       "      <th>short_emp</th>\n",
       "      <th>emp_length_num</th>\n",
       "      <th>home_ownership</th>\n",
       "      <th>dti</th>\n",
       "      <th>purpose</th>\n",
       "      <th>term</th>\n",
       "      <th>last_delinq_none</th>\n",
       "      <th>last_major_derog_none</th>\n",
       "      <th>revol_util</th>\n",
       "      <th>total_rec_late_fee</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <td>4104</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>18915</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>44721</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>21933</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>20111</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>13839</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>15773</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>27211</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>17372</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <td>5410</td>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>800 rows × 12 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "       grade  sub_grade  short_emp  emp_length_num  home_ownership  dti  \\\n",
       "4104       1          1          1               0               0    1   \n",
       "18915      0          0          0               0               1    1   \n",
       "44721      0          0          0               1               1    1   \n",
       "21933      0          0          0               0               0    1   \n",
       "20111      1          1          0               1               0    0   \n",
       "...      ...        ...        ...             ...             ...  ...   \n",
       "13839      1          1          0               1               0    1   \n",
       "15773      1          1          0               1               1    0   \n",
       "27211      1          1          0               0               1    1   \n",
       "17372      1          0          0               1               0    0   \n",
       "5410       1          1          0               1               0    1   \n",
       "\n",
       "       purpose  term  last_delinq_none  last_major_derog_none  revol_util  \\\n",
       "4104         0     0                 0                      1           0   \n",
       "18915        0     0                 0                      1           0   \n",
       "44721        0     0                 1                      1           0   \n",
       "21933        0     0                 1                      1           0   \n",
       "20111        0     0                 0                      1           0   \n",
       "...        ...   ...               ...                    ...         ...   \n",
       "13839        0     1                 1                      1           1   \n",
       "15773        0     0                 0                      1           1   \n",
       "27211        0     1                 1                      1           0   \n",
       "17372        0     1                 0                      0           0   \n",
       "5410         0     1                 0                      0           1   \n",
       "\n",
       "       total_rec_late_fee  \n",
       "4104                    0  \n",
       "18915                   0  \n",
       "44721                   0  \n",
       "21933                   0  \n",
       "20111                   0  \n",
       "...                   ...  \n",
       "13839                   0  \n",
       "15773                   0  \n",
       "27211                   0  \n",
       "17372                   0  \n",
       "5410                    0  \n",
       "\n",
       "[800 rows x 12 columns]"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 将以上非数值数据映射为数值型。\n",
    "d = defaultdict(LabelEncoder)\n",
    "data = data.apply(lambda x : d[x.name].fit_transform(x))\n",
    "X_train = data.iloc[:800, :-1]\n",
    "y_train = data.iloc[:800, -1]\n",
    "test_X = data.iloc[800:, :-1]\n",
    "test_y = data.iloc[800:, -1]\n",
    "display(X_train)\n",
    "\n",
    "# 特征二值化\n",
    "# 由于特征值太过复杂，不利于处理。我们根据均值来二值化\n",
    "for i in X_train.columns:\n",
    "    mean = np.mean(X_train[i])\n",
    "    for j in range(len(X_train[i])):\n",
    "        X_train[i].values[j] = 1 if X_train[i].values[j]>mean else 0\n",
    "for i in test_X.columns:\n",
    "    mean = np.mean(test_X[i])\n",
    "    for j in range(len(test_X[i])):\n",
    "        test_X[i].values[j] = 1 if test_X[i].values[j]>mean else 0\n",
    "display(X_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 171,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import  Counter\n",
    "from tqdm import tqdm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 172,
   "metadata": {},
   "outputs": [],
   "source": [
    "class DecisionTreeID3:\n",
    "    def __init__(self):\n",
    "        pass\n",
    "    def calc_entropy(self):\n",
    "        '''计算信息熵、条件熵和信息增益'''\n",
    "        # 把标签放在数据最后一列，方便create_tree处理\n",
    "        self.X = pd.concat([self.X, self.y], axis=1)\n",
    "        # ************ 计算信息熵 **************\n",
    "        yes = np.asarray(self.X[self.X[self.X.columns[-1]]==1])\n",
    "        no = np.asarray(self.X[self.X[self.X.columns[-1]]==0])\n",
    "        P_yes = len(yes)/len(self.X)\n",
    "        P_no = len(no)/len(self.X)\n",
    "        self.HX = - P_yes*np.log2(P_yes)- P_no*np.log2(P_no)\n",
    "#         display(\"信息熵 = \" +str(self.HX))\n",
    "        # ************ 计算条件熵 **************\n",
    "        # H存放条件熵\n",
    "        self.Gda = []\n",
    "        # 遍历每一特征列。除了标签列\n",
    "        for i in self.X.columns[:-1]:\n",
    "            # 存放条件熵\n",
    "            Hi = 0\n",
    "            # 获取当前特征每种情况出现的次数，以便计算每个情况各自的概率\n",
    "            condProbCollections = Counter(self.X[i]).items()\n",
    "            # 每种特征可能有N中情况，累加\n",
    "            for k in condProbCollections:\n",
    "                # 获取当前条件X发生的总样本(包含所有列)\n",
    "                samples_of_current = self.X[self.X[i]==k[0]]\n",
    "                # 获取当前条件X发生的总样本(仅包含当前特征列)\n",
    "                samples_of_current_features = samples_of_current[i]\n",
    "                # 获取当前条件X发生下，被判定为安全和不安全的总次数\n",
    "                total = len(samples_of_current_features)\n",
    "                # 安全总次数\n",
    "                k_safe = len(samples_of_current[samples_of_current[samples_of_current.columns[-1]]==1])\n",
    "                # 不安全总次数\n",
    "                k_unsafe = total - k_safe\n",
    "                # 计算安全和不安全的概率\n",
    "                P_k_safe = k_safe/total\n",
    "                P_k_unsafe = k_unsafe/total\n",
    "                # 累加条件熵\n",
    "                log_P_k_safe = 0 if P_k_safe==0 else np.log2(P_k_safe) # 防止出现0值报错\n",
    "                log_P_k_unsafe = 0 if P_k_unsafe==0 else np.log2(P_k_unsafe) # 防止出现0值报错\n",
    "                Hi +=  - (total/len(self.X))*(P_k_safe * log_P_k_safe + P_k_unsafe * log_P_k_unsafe)\n",
    "            # 保存信息增益\n",
    "            self.Gda.append({\"value\":self.HX - Hi, \"feature\":i})\n",
    "#         print(\"信息增益为\")\n",
    "#         print(self.Gda)\n",
    "    def create_tree(self, node=False):\n",
    "        '''构建决策树结构。决策树信息存储在JSON字典当中\n",
    "        \n",
    "        Parameters\n",
    "        -----\n",
    "        node: Series类型，用于传递当前节点包含的信息\n",
    "        \n",
    "        Return\n",
    "        -----\n",
    "        tree: 构建好的树json结构\n",
    "        '''\n",
    "        # 递归出口\n",
    "        if len(self.Gda)==0:\n",
    "            return node.iloc[:1,-1].values[0]\n",
    "        # 获取第一个特征列\n",
    "        feature = self.Gda[0]['feature']\n",
    "        # 删除该列，以便递归时不会重复到达这里\n",
    "        del self.Gda[0]\n",
    "        # 获取当前特征每种情况出现的次数，以便计算每个情况各自的概率\n",
    "        condProbCollections = Counter(self.X[feature]).items()\n",
    "#         print(feature)\n",
    "#         print(condProbCollections)\n",
    "        # 定义树字典。必须使用特征feature作为键名\n",
    "        tree = {feature:{}}\n",
    "        for [value,counts] in condProbCollections:\n",
    "#             print(condProbCollections)\n",
    "#             print(value)\n",
    "            tree[feature][value] = self.create_tree(self.X[self.X[feature]==value])\n",
    "        # 保存树结构\n",
    "        self.tree = tree\n",
    "        return tree\n",
    "    def fit(self, X, y):\n",
    "        '''训练\n",
    "        \n",
    "        Parameters\n",
    "        -----\n",
    "        X: 训练数据，形如 [样本数量，特征数量]\n",
    "        y: 类数组类型，形状为：[样本数量]\n",
    "        '''\n",
    "        self.X = X\n",
    "        self.y = y\n",
    "        self.calc_entropy()\n",
    "        self.create_tree()\n",
    "    def predict_item(self, x, node=False):\n",
    "        '''构建决策树结构。决策树信息存储在JSON字典当中\n",
    "        \n",
    "        Parameters\n",
    "        -----\n",
    "        node: Series类型，用于传递当前节点包含的信息\n",
    "        \n",
    "        Return\n",
    "        -----\n",
    "        tree: 构建好的树json结构\n",
    "        '''\n",
    "        if node==0 or node==1:\n",
    "            return node\n",
    "        label = -1\n",
    "        # 获取当前节点名\n",
    "        key = next(iter(node))\n",
    "        # 如果当前节点的值等于0，递归0下面的分支，否则1\n",
    "        if x[key].values[0] == 0:\n",
    "            label = self.predict_item(x, node=node[key][0])\n",
    "        else:\n",
    "            label = self.predict_item(x, node=node[key][1])\n",
    "        return label\n",
    "    def predict(self, X):\n",
    "        '''对样本进行预测\n",
    "        Parameters:\n",
    "        X: 类数组类型，可以是List也可以是Ndarray，形状为： [样本数量,特征数量]\n",
    "        Returns:\n",
    "        数组类型，预测结果\n",
    "        '''\n",
    "        result = []\n",
    "        for i in range(len(X)):\n",
    "            result.append(self.predict_item(X.iloc[i:i+1,], node=self.tree))\n",
    "        return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "dt = DecisionTreeID3()\n",
    "dt.fit(X_train, y_train)\n",
    "result = dt.predict(test_X)\n",
    "display(np.sum(result==test_y)/len(result))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 159,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'a': 1}"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "{'b': 2}"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "{'c': 3}"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "a=[{\"a\":1},{\"b\":2},{\"c\":3}]\n",
    "c = iter(a)\n",
    "display(next(c))\n",
    "display(next(c))\n",
    "display(next(c))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
